package com.cyy.common.aspect;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSON;
import com.cyy.common.annotation.OperationLog;
import com.cyy.common.pojo.entity.SysLog;
import com.cyy.common.service.SysLogService;
import com.cyy.common.utils.IpUtils;
import com.cyy.common.utils.RequestContextUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Objects;
import java.util.Optional;

/**
 * 操作日志AOP
 */
@Slf4j
@Aspect
@Component
public class OperationLogAspect {

    @Resource
    private SysLogService sysLogService;


    /**
     * 切入点设置
     *
     * @param operationLog OperationLog
     */
    @Pointcut(value = "@annotation(operationLog)")
    public void pointcut(OperationLog operationLog) {
    }


    @Around(value = "pointcut(operationLog)", argNames = "pjp,operationLog")
    public Object odAround(ProceedingJoinPoint pjp, OperationLog operationLog) {

        Object res = null;
        Throwable ex = null;
        try {
            res = pjp.proceed();
        } catch (Throwable e) {
            ex = e;
            throw new RuntimeException(e);
        } finally {
            //日志记录
            handle(pjp, operationLog, ex);
        }

        return res;
    }


    private void handle(ProceedingJoinPoint pjp, OperationLog operationLog, Throwable ex) {

        HttpServletRequest request = RequestContextUtils.getRequest();

        SysLog sysLog = new SysLog();
        sysLog.setTitle(operationLog.value());
        sysLog.setClassPath(pjp.getTarget().getClass().getName());
        sysLog.setRequestMethod(request.getMethod());
        sysLog.setUrl(request.getRequestURI());
        sysLog.setIp(IpUtils.getIpAddr(request));
        sysLog.setParams(getParamsJson(pjp));
        sysLog.setUserId(Integer.valueOf((String) Optional.ofNullable(StpUtil.getLoginIdDefaultNull()).orElse("-1")));
        if (Objects.nonNull(ex)) {
            sysLog.setErrorMsg(ex.getMessage());
            sysLog.setStatus("E");
        } else {
            sysLog.setStatus("A");
        }
        sysLogService.save(sysLog);

    }


    private String getParamsJson(ProceedingJoinPoint pjp) {
        Object[] args = pjp.getArgs();//获取参数列表
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;// 获取方法实例
        String[] parameterNames = methodSignature.getParameterNames();//获取参数名列表

        // 创建存储map
        HashMap<String, Object> paramMap = new HashMap<>();
        for (int i = 0; i < parameterNames.length; i++) {
            paramMap.put(parameterNames[i], args[i]);
        }

        return JSON.toJSONString(paramMap);
    }
}
